﻿Imports System
Imports System.CodeDom
Imports System.Collections.Generic
Imports System.Globalization
Imports System.Reflection
Imports System.Text
Imports System.Workflow.ComponentModel.Compiler

Namespace System.Workflow.Activities.Rules
    Friend Class PropertyReferenceExpression
        Inherits RuleExpressionInternal
        ' Methods
        Friend Overrides Sub AnalyzeUsage(ByVal expression As CodeExpression, ByVal analysis As RuleAnalysis, ByVal isRead As Boolean, ByVal isWritten As Boolean, ByVal qualifier As RulePathQualifier)
            Dim expression2 As CodePropertyReferenceExpression = DirectCast(expression, CodePropertyReferenceExpression)
            Dim targetObject As CodeExpression = expression2.TargetObject
            If (analysis.Validation.ExpressionInfo(targetObject) Is Nothing) Then
                Dim exception As New InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Messages.ExpressionNotValidated, New Object(0  - 1) {}))
                exception.Data.Item("ErrorObject") = targetObject
                Throw exception
            End If
            Dim info2 As RulePropertyExpressionInfo = [TryCast](analysis.Validation.ExpressionInfo(expression2),RulePropertyExpressionInfo)
            If (info2 Is Nothing) Then
                Dim exception2 As New InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Messages.ExpressionNotValidated, New Object(0  - 1) {}))
                exception2.Data.Item("ErrorObject") = expression2
                Throw exception2
            End If
            Dim propertyInfo As PropertyInfo = info2.PropertyInfo
            Dim attributedExprs As New List([Of] CodeExpression)
            analysis.AnalyzeRuleAttributes(propertyInfo, targetObject, qualifier, Nothing, Nothing, attributedExprs)
            If Not attributedExprs.Contains(targetObject) Then
                RuleExpressionWalker.AnalyzeUsage(analysis, targetObject, isRead, isWritten, New RulePathQualifier(propertyInfo.Name, qualifier))
            End If
        End Sub

        Friend Overrides Function Clone(ByVal expression As CodeExpression) As CodeExpression
            Dim expression2 As CodePropertyReferenceExpression = DirectCast(expression, CodePropertyReferenceExpression)
            Return New CodePropertyReferenceExpression { _
                .PropertyName = expression2.PropertyName, _
                .TargetObject = RuleExpressionWalker.Clone(expression2.TargetObject) _
            }
        End Function

        Friend Overrides Sub Decompile(ByVal expression As CodeExpression, ByVal stringBuilder As StringBuilder, ByVal parentExpression As CodeExpression)
            Dim expression2 As CodePropertyReferenceExpression = DirectCast(expression, CodePropertyReferenceExpression)
            Dim targetObject As CodeExpression = expression2.TargetObject
            If (targetObject Is Nothing) Then
                Dim exception As New RuleEvaluationException(String.Format(CultureInfo.CurrentCulture, Messages.NullPropertyTarget, New Object() { expression2.PropertyName }))
                exception.Data.Item("ErrorObject") = expression2
                Throw exception
            End If
            RuleExpressionWalker.Decompile(stringBuilder, targetObject, expression2)
            stringBuilder.Append("."c)
            stringBuilder.Append(expression2.PropertyName)
        End Sub

        Friend Overrides Function Evaluate(ByVal expression As CodeExpression, ByVal execution As RuleExecution) As RuleExpressionResult
            Dim expression2 As CodePropertyReferenceExpression = DirectCast(expression, CodePropertyReferenceExpression)
            Dim targetObject As Object = RuleExpressionWalker.Evaluate(execution, expression2.TargetObject).Value
            Dim info As RulePropertyExpressionInfo = [TryCast](execution.Validation.ExpressionInfo(expression2),RulePropertyExpressionInfo)
            If (info Is Nothing) Then
                Dim exception As New InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Messages.ExpressionNotValidated, New Object(0  - 1) {}))
                exception.Data.Item("ErrorObject") = expression2
                Throw exception
            End If
            Return New RulePropertyResult(info.PropertyInfo, targetObject, Nothing)
        End Function

        Friend Overrides Function Match(ByVal expression As CodeExpression, ByVal comperand As CodeExpression) As Boolean
            Dim expression2 As CodePropertyReferenceExpression = DirectCast(expression, CodePropertyReferenceExpression)
            Dim expression3 As CodePropertyReferenceExpression = DirectCast(comperand, CodePropertyReferenceExpression)
            Return ((expression2.PropertyName = expression3.PropertyName) AndAlso RuleExpressionWalker.Match(expression2.TargetObject, expression3.TargetObject))
        End Function

        Friend Overrides Function Validate(ByVal expression As CodeExpression, ByVal validation As RuleValidation, ByVal isWritten As Boolean) As RuleExpressionInfo
            Dim newParent As CodePropertyReferenceExpression = DirectCast(expression, CodePropertyReferenceExpression)
            If (newParent.TargetObject Is Nothing) Then
                Dim error As New ValidationError(String.Format(CultureInfo.CurrentCulture, Messages.NullPropertyTarget, New Object() { newParent.PropertyName }), &H53D)
                [error].UserData.Item("ErrorObject") = newParent
                validation.Errors.Add([error])
                Return Nothing
            End If
            If Not validation.PushParentExpression(newParent) Then
                Return Nothing
            End If
            Dim info As RuleExpressionInfo = RuleExpressionWalker.Validate(validation, newParent.TargetObject, False)
            validation.PopParentExpression
            If (info Is Nothing) Then
                Return Nothing
            End If
            Dim expressionType As Type = info.ExpressionType
            If (expressionType Is Nothing) Then
                Return Nothing
            End If
            If (expressionType Is GetType(NullLiteral)) Then
                Dim error2 As New ValidationError(String.Format(CultureInfo.CurrentCulture, Messages.NullPropertyTarget, New Object() { newParent.PropertyName }), &H546)
                error2.UserData.Item("ErrorObject") = newParent
                validation.Errors.Add(error2)
                Return Nothing
            End If
            Dim nonPublic As Boolean = False
            Dim bindingFlags As BindingFlags = (BindingFlags.FlattenHierarchy Or (BindingFlags.Public Or (BindingFlags.Static Or BindingFlags.Instance)))
            If validation.AllowInternalMembers(expressionType) Then
                bindingFlags = (bindingFlags Or BindingFlags.NonPublic)
                nonPublic = True
            End If
            Dim item As PropertyInfo = RuleValidation.ResolveProperty(expressionType, newParent.PropertyName, bindingFlags)
            If (item Is Nothing) Then
                Dim error3 As New ValidationError(String.Format(CultureInfo.CurrentCulture, Messages.UnknownProperty, New Object() { newParent.PropertyName, RuleDecompiler.DecompileType(expressionType) }), &H54A)
                error3.UserData.Item("ErrorObject") = newParent
                validation.Errors.Add(error3)
                Return Nothing
            End If
            If (item.PropertyType Is Nothing) Then
                Dim error4 As New ValidationError(String.Format(CultureInfo.CurrentCulture, Messages.CouldNotDetermineMemberType, New Object() { newParent.PropertyName }), &H194)
                error4.UserData.Item("ErrorObject") = newParent
                validation.Errors.Add(error4)
                Return Nothing
            End If
            Dim accessorMethod As MethodInfo = If(isWritten, item.GetSetMethod(nonPublic), item.GetGetMethod(nonPublic))
            If (accessorMethod Is Nothing) Then
                Dim format As String = If(isWritten, Messages.UnknownPropertySet, Messages.UnknownPropertyGet)
                Dim error5 As New ValidationError(String.Format(CultureInfo.CurrentCulture, format, New Object() { newParent.PropertyName, RuleDecompiler.DecompileType(expressionType) }), &H54A)
                error5.UserData.Item("ErrorObject") = newParent
                validation.Errors.Add(error5)
                Return Nothing
            End If
            If Not validation.ValidateMemberAccess(newParent.TargetObject, expressionType, accessorMethod, newParent.PropertyName, newParent) Then
                Return Nothing
            End If
            Dim customAttributes As Object() = item.GetCustomAttributes(GetType(RuleAttribute), True)
            If ((Not customAttributes Is Nothing) AndAlso (customAttributes.Length > 0)) Then
                Dim stack As New Stack([Of] MemberInfo)
                stack.Push(item)
                Dim flag2 As Boolean = True
                Dim attribute As RuleAttribute
                For Each attribute In customAttributes
                    If Not attribute.Validate(validation, item, expressionType, Nothing) Then
                        flag2 = False
                    End If
                Next
                stack.Pop
                If Not flag2 Then
                    Return Nothing
                End If
            End If
            Return New RulePropertyExpressionInfo(item, item.PropertyType, False)
        End Function

    End Class
End Namespace

